package com.jxdinfo.hussar.activitidemo.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.jxdinfo.hussar.activitidemo.bean.*;
import com.jxdinfo.hussar.activitidemo.utils.DateUtil;
import net.sf.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.jxdinfo.hussar.activitidemo.dao.TdbYjMFlowDetailMapper;
import com.jxdinfo.hussar.activitidemo.dao.TdbYjMFlowMapper;
import com.jxdinfo.hussar.activitidemo.dao.TdbYjMFlowReferenceMapper;
import com.jxdinfo.hussar.activitidemo.dao.TdbYjMFlowStepdetailMapper;
import com.jxdinfo.hussar.activitidemo.dao.TdbYjMFlowTraintypeCodeMapper;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 
 * @since 2019-03-20
 */
@Service
@Transactional
public class TdbYjMFlowServiceImpl implements  ITdbYjMFlowService{
	@Autowired
	TdbYjMFlowMapper flowMapper;
	@Autowired
	TdbYjMFlowDetailMapper flowDetailMapper;
	@Autowired
	TdbYjMFlowStepdetailMapper stepDetailMapper;
	@Autowired
	TdbYjMFlowReferenceMapper tdbYjMFlowReferenceMapper;
	@Autowired
	TdbYjMFlowTraintypeCodeMapper tdbYjMFlowTraintypeCodeMapper;

	@Override
	public Page<TdbYjMFlow> selectByCondition(Page<TdbYjMFlow> page, TdbYjMFlow info){
		List<TdbYjMFlow> list = this.flowMapper.selectByCondition(page, info);
		page.setRecords(list);
		Integer count = this.flowMapper.selectCountByCondition(info);
		page.setTotal(count);
		return page;
	}
	@Override
	public Map<String,Object> insertFlowInfo(TdbYjMFlow tdbYjMFlow) {
		Map<String,Object> map = new HashMap<String,Object>();
		Integer check = flowMapper.checkFlowName(tdbYjMFlow);
		if (check>0){
			map.put("code", "400");
			map.put("mesg", "处理流程名称重复！");
			return map;
		}
		tdbYjMFlow.setdCreateDate(DateUtil.getNowDate("yyyy-MM-dd HH:mm:ss"));
		tdbYjMFlow.setsStatus("1");
		//向流程主表中插入数据
		flowMapper.insertFlowInfo(tdbYjMFlow);
		
		Map<String,String> keyMap = new HashMap<String,String>();
		//取得流程节点信息
		JSONObject jsonObject = JSONObject.parseObject(tdbYjMFlow.getStepInfoMap());
		//取得流程节点对应的详细信息
	    JSONObject stepDetailJsonObject = JSONObject.parseObject(tdbYjMFlow.getStepDetailMap());
    	Set set = jsonObject.keySet();
    	Iterator iterator1 = set.iterator();
    	//循环做成节点id和uuid的映射关系
    	while(iterator1.hasNext()){
    		String key = (String)iterator1.next();
    		JSONObject stepObj = jsonObject.getJSONObject(key);
    		String flowStepId = stepObj.getString("sFlowStepid");
    		String uuId = IdWorker.get32UUID();
    		keyMap.put(flowStepId, uuId);
    	}
    	List<TdbYjMFlowDetail> list = new ArrayList<TdbYjMFlowDetail>(); 
    	Iterator iterator = set.iterator();
    	while(iterator.hasNext()){
    		String key = (String)iterator.next();
    		JSONObject stepObj = jsonObject.getJSONObject(key);
    		String sFlowStepid =stepObj.getString("sFlowStepid");
    		String sFatherid = stepObj.getString("sFatherid");
    		//根据映射关系，给节点id和父节点id重新赋值
    		sFlowStepid = getUUIdById(keyMap,sFlowStepid);
    		sFatherid = getUUIdById(keyMap,sFatherid);
    		TdbYjMFlowDetail flowDetail = new TdbYjMFlowDetail();
    		
    		flowDetail.setsFlowStepid(sFlowStepid);
    		flowDetail.setsFlowId(tdbYjMFlow.getsFlowId());
    		flowDetail.setsTitle(stepObj.getString("sTitle"));
    		flowDetail.setsContent(stepObj.getString("sContent"));
    		flowDetail.setsFatherid(sFatherid);
    		flowDetail.setsNytype(stepObj.getString("sNytype"));
    		flowDetail.setiSort(stepObj.getString("iSort"));
    		flowDetail.setsNewFlowId(stepObj.getString("sNewFlowId"));
    		flowDetail.setsMbookStepid(stepObj.getString("sMbookStepid"));
    		list.add(flowDetail);
    	}

    	 //向流程步骤表插入数据
		flowDetailMapper.insertFlowDetailInfo(list);
		
		Set stepDetaiSet = stepDetailJsonObject.keySet();
    	Iterator stepDetailIterator = stepDetaiSet.iterator();
    	List<TdbYjMFlowStepdetail> stepDetaillist = new ArrayList<TdbYjMFlowStepdetail>();
    	List<TdbYjMFlowReference> stepReferencelist = new ArrayList<TdbYjMFlowReference>();
    	while(stepDetailIterator.hasNext()){
    		TdbYjMFlowStepdetail stepDetail = new TdbYjMFlowStepdetail();
    		TdbYjMFlowReference  stepReference = new TdbYjMFlowReference();
    		String key = (String)stepDetailIterator.next();
    		JSONObject stepObj = stepDetailJsonObject.getJSONObject(key);
    		String sDriverOperate =stepObj.getString("sDriverOperate");
    		String sEngineerOperate =stepObj.getString("sEngineerOperate");
    		String sNotice =stepObj.getString("sNotice");
    		String sFileName =stepObj.getString("sFileName");
    		String sFileId =stepObj.getString("sFileId");
    		String sPage =stepObj.getString("sPage");
    		String sLineNum =stepObj.getString("sLineNum");
    		String sFlowStepid =stepObj.getString("sFlowStepid");
    		sFlowStepid = getUUIdById(keyMap,sFlowStepid);
    		//构造步骤明细数据对象的内容
    		stepDetail.setsFlowStepid(sFlowStepid);
    		stepDetail.setsDriverOperate(sDriverOperate);
    		stepDetail.setsEngineerOperate(sEngineerOperate);
    		stepDetail.setsNotice(sNotice);
    		stepDetaillist.add(stepDetail);
    		
    		//构造步骤参考文件数据对象的内容
    		stepReference.setsFlowStepid(sFlowStepid);
    		stepReference.setsFileName(sFileName);
    		stepReference.setsFileId(sFileId);
    		stepReference.setsPage(sPage);
    		stepReference.setsLineNum(sLineNum);
    		stepReferencelist.add(stepReference);
    		
    	}
    	//插入车型代码
    	this.insertFlowTraintypeCode(tdbYjMFlow.getsTraintype(), tdbYjMFlow.getsCode(), tdbYjMFlow.getsFlowId());
		 //向步骤明细表插入数据
    	stepDetailMapper.insertFlowStepDetail(stepDetaillist);
    	//向步骤参考文件表插入数据
    	tdbYjMFlowReferenceMapper.insertFlowStepReference(stepReferencelist);
		map.put("code", "200");
		map.put("mesg", "操作成功");
		return map;
	}
	/**
	 * 根据页面做成的步骤id转换成UUId
	 * @param map
	 * @param stepId
	 * @return
	 */
	private String getUUIdById(Map<String,String> map,String stepId){
		if(stepId!=null && !"".equals(stepId)){
			return map.get(stepId);
		}else
		{
			return stepId;
		}
		
	}
	@Override
	public Map<String, Object> getFlowInfo(TdbYjMFlow tdbYjMFlow) {
		Map<String,Object> map = new HashMap<String,Object>();
		//取得流程表主表信息，并保存在map中
		TdbYjMFlow flowInfo = flowMapper.selectFlowInfo(tdbYjMFlow);

		//取得流程步骤信息
		List<TdbYjMFlowDetail> flowStepInfoList =  flowDetailMapper.selectFlowDetail(tdbYjMFlow);
		List<String> flowStepIdList = new ArrayList<String>();
		map.put("flowStepInfo", flowStepInfoList);
		//将流程id存入list中，为了查询流程详细表和流程参考文件表作为in条件
		for(int i=0;i<flowStepInfoList.size();i++){
			flowStepIdList.add(flowStepInfoList.get(i).getsFlowStepid());
		}
		//查询流程步骤详细信息
		List<TdbYjMFlowReference> referenceList = tdbYjMFlowReferenceMapper.selectFlowReference(flowStepIdList);
		map.put("flowStepReferenceInfo", referenceList);
		//查询流程步骤参考文件信息
		List<TdbYjMFlowStepdetail> stepDetailList =  stepDetailMapper.selectStepDetail(flowStepIdList);
		map.put("flowStepDetailInfo", stepDetailList);
		
		//处置流程车型代码
		List<String> trainList = tdbYjMFlowTraintypeCodeMapper.selectTrainTypeByFlowId(flowInfo.getsFlowId());
		List<String> codeList = tdbYjMFlowTraintypeCodeMapper.selectTrainCodeByFlowId(flowInfo.getsFlowId());
		flowInfo.setsTraintype(StringUtils.join(trainList.toArray(), ","));
		flowInfo.setsCode(this.getTrainCode(codeList));
		map.put("flowInfo", flowInfo);
		return map;
	}
	@Override
	public Map<String, Object> updateFlowInfo(TdbYjMFlow tdbYjMFlow) {
		Map<String,Object> map = new HashMap<String,Object>();
		Integer check = flowMapper.checkFlowName(tdbYjMFlow);
		if (check>0){
			map.put("code", "400");
			map.put("mesg", "处理流程名称重复！");
			return map;
		}
		tdbYjMFlow.setdEditDate(DateUtil.getNowDate("yyyy-MM-dd HH:mm:ss"));
		//修改流程主表数据
		flowMapper.updateFlowInfo(tdbYjMFlow);
		
		Map<String,String> keyMap = new HashMap<String,String>();
		//取得流程节点信息
		JSONObject jsonObject = JSONObject.parseObject(tdbYjMFlow.getStepInfoMap());
		//取得流程节点对应的详细信息
	    JSONObject stepDetailJsonObject = JSONObject.parseObject(tdbYjMFlow.getStepDetailMap());
    	Set set = jsonObject.keySet();
    	Iterator iterator1 = set.iterator();
    	//循环做成节点id和uuid的映射关系
    	while(iterator1.hasNext()){
    		String key = (String)iterator1.next();
    		JSONObject stepObj = jsonObject.getJSONObject(key);
    		String flowStepId = stepObj.getString("sFlowStepid");
    		String uuId = IdWorker.get32UUID();
    		keyMap.put(flowStepId, uuId);
    	}
    	List<TdbYjMFlowDetail> list = new ArrayList<TdbYjMFlowDetail>(); 
    	Iterator iterator = set.iterator();
    	while(iterator.hasNext()){
    		String key = (String)iterator.next();
    		JSONObject stepObj = jsonObject.getJSONObject(key);
    		String sFlowStepid =stepObj.getString("sFlowStepid");
    		String sFatherid = stepObj.getString("sFatherid");
    		//根据映射关系，给节点id和父节点id重新赋值
    		sFlowStepid = getUUIdById(keyMap,sFlowStepid);
    		sFatherid = getUUIdById(keyMap,sFatherid);
    		TdbYjMFlowDetail flowDetail = new TdbYjMFlowDetail();
    		
    		flowDetail.setsFlowStepid(sFlowStepid);
    		flowDetail.setsFlowId(tdbYjMFlow.getsFlowId());
    		flowDetail.setsTitle(stepObj.getString("sTitle"));
    		flowDetail.setsContent(stepObj.getString("sContent"));
    		flowDetail.setsFatherid(sFatherid);
    		flowDetail.setsNytype(stepObj.getString("sNytype"));
    		flowDetail.setiSort(stepObj.getString("iSort"));
    		flowDetail.setsNewFlowId(stepObj.getString("sNewFlowId"));
    		flowDetail.setsMbookStepid(stepObj.getString("sMbookStepid"));
    		list.add(flowDetail);
    	}

    	 //先清除流程步骤表的数据，然后向流程步骤表插入数据
    	flowDetailMapper.deleteFlowDetail(tdbYjMFlow.getsFlowId());
		flowDetailMapper.insertFlowDetailInfo(list);
		
		Set stepDetaiSet = stepDetailJsonObject.keySet();
    	Iterator stepDetailIterator = stepDetaiSet.iterator();
    	List<TdbYjMFlowStepdetail> stepDetaillist = new ArrayList<TdbYjMFlowStepdetail>();
    	List<TdbYjMFlowReference> stepReferencelist = new ArrayList<TdbYjMFlowReference>();
    	List<String> stepDetailIdsList = new ArrayList<String>();
    	List<String> stepReferenceIdsList = new ArrayList<String>();
    	while(stepDetailIterator.hasNext()){
    		TdbYjMFlowStepdetail stepDetail = new TdbYjMFlowStepdetail();
    		TdbYjMFlowReference  stepReference = new TdbYjMFlowReference();
    		String key = (String)stepDetailIterator.next();
    		JSONObject stepObj = stepDetailJsonObject.getJSONObject(key);
    		String sDriverOperate =stepObj.getString("sDriverOperate");
    		String sEngineerOperate =stepObj.getString("sEngineerOperate");
    		String sNotice =stepObj.getString("sNotice");
    		String sFileName =stepObj.getString("sFileName");
    		String sFileId =stepObj.getString("sFileId");
    		String sPage =stepObj.getString("sPage");
    		String sLineNum =stepObj.getString("sLineNum");
    		String sFlowStepid =stepObj.getString("sFlowStepid");
    		sFlowStepid = getUUIdById(keyMap,sFlowStepid);
    		//构造步骤明细数据对象的内容
    		stepDetail.setsFlowStepid(sFlowStepid);
    		stepDetail.setsDriverOperate(sDriverOperate);
    		stepDetail.setsEngineerOperate(sEngineerOperate);
    		stepDetail.setsNotice(sNotice);
    		stepDetaillist.add(stepDetail);
    		stepDetailIdsList.add(sFlowStepid);
    		
    		//构造步骤参考文件数据对象的内容
    		stepReference.setsFlowStepid(sFlowStepid);
    		stepReference.setsFileName(sFileName);
    		stepReference.setsFileId(sFileId);
    		stepReference.setsPage(sPage);
    		stepReference.setsLineNum(sLineNum);
    		stepReferencelist.add(stepReference);
    		stepReferenceIdsList.add(sFlowStepid);
    		
    	}
		
		 //先删除步骤明细表数据，然后向步骤明细表插入数据
    	stepDetailMapper.deleteStepDetail(stepDetailIdsList);
    	stepDetailMapper.insertFlowStepDetail(stepDetaillist);
    	//先删除步骤参考文件表数据，然后向步骤参考文件表插入数据
    	tdbYjMFlowReferenceMapper.deleteFlowReference(stepReferenceIdsList);
    	tdbYjMFlowReferenceMapper.insertFlowStepReference(stepReferencelist);
		
    	//先删除车辆代码表数据，在插入
    	tdbYjMFlowTraintypeCodeMapper.deleteTrainCodeByFlowId(tdbYjMFlow.getsFlowId());
    	this.insertFlowTraintypeCode(tdbYjMFlow.getsTraintype(), tdbYjMFlow.getsCode(), tdbYjMFlow.getsFlowId());
		map.put("code", "200");
		map.put("mesg", "操作成功");
    	return map;
	}
	@Override
	public Map<String, Object> deleteFlowInfo(String ids) {
		Map<String,Object> map= new HashMap<String,Object>();
		List<TdbYjMFlow> list=(List<TdbYjMFlow>)JSONArray.toList(JSONArray.fromObject(ids), TdbYjMFlow.class);
		for (TdbYjMFlow l:list){
			flowMapper.deleteFlowInfo(l);
		}

		return map;
	}

	@Override
	public Map<String, Object> updateFlowInfoStatus(TdbYjMFlow info) {
		Map<String,Object> map= new HashMap<String,Object>();
		JSONArray jsonArray = JSONArray.fromObject(info.getsFlowId());//把String转换为json
		List<TdbYjMFlow> list = JSONArray.toList(jsonArray,TdbYjMFlow.class);
		list.forEach(p->{
			p.setsStatus(info.getsStatus());
			flowMapper.updateFlowInfoStatus(p);
		});
		return map;
	}

	@Override
	public List<Map> selectApplyDept(String term) {
		// TODO Auto-generated method stub
		return flowMapper.selectApplyDept(term);
	}
	@Override
	public Page<Map> selectYjsc(Page<Map> page,String term) {
		List<Map> list = this.flowMapper.selectYjsc(page, term);
		page.setRecords(list);
		Integer count = this.flowMapper.selectYjscCount(term);
		page.setTotal(count);
		return page;
	}
	@Override
	public Page<Map> selectCkwj(Page<Map> page, String term) {
		List<Map> list = this.flowMapper.selectCkwj(page, term);
		page.setRecords(list);
		page.setTotal(list.size());
		page.getPages();

		return page;
	}
	
	/**
	 * 插入处置流程车型代码（故障代码解析）
	 * trainType:车辆型号
	 * code:故障代码
	 * flowId:处置流程id
	 */
	public void insertFlowTraintypeCode(String trainType,String code,String flowId){
		List<String> list = new ArrayList<>();//存放解析后的故障代码
		String[] trains = trainType.split(",");
		String[] codes = code.split(",");
		for (int i = 0; i <codes.length ; i++) {
			if(codes[i].contains("~")){
				List<Integer> codeList = new ArrayList<>();
				String[] codeLine = codes[i].split("~");
				for (int k = 0; k < codeLine.length; k++) {
					codeList.add(Integer.parseInt(codeLine[k]));
				}
				Integer max = Collections.max(codeList);
				Integer min = Collections.min(codeList);
				for(int j=min;j<=max;j++){
					list.add(String.valueOf(j));
				}
			}else{
				list.add(codes[i]);
			}
		}
		for (int i = 0; i < trains.length; i++) {
			String traintype = trains[i];
			list.forEach(p->{
				TdbYjMFlowTraintypeCode flowTraintypeCode = new TdbYjMFlowTraintypeCode();
				flowTraintypeCode.setsId(IdWorker.get32UUID());
				flowTraintypeCode.setsFlowId(flowId);
				flowTraintypeCode.setsCode(p);
				flowTraintypeCode.setsTraintype(traintype);
				tdbYjMFlowTraintypeCodeMapper.insertFlowInfo(flowTraintypeCode);
			});
		}
	}

	/**
	 * 故障代码拼接
	 * @param list 故障代码集合
	 * @return 拼接后的故障代码
	 */
	public String getTrainCode(List<String> list){
		StringBuffer buffer = new StringBuffer();
		list.removeAll(Collections.singleton(null));
		if(list==null||list.size()==0)
			return "";
		List<Integer> codes = new ArrayList<>();
		list.forEach(p->{
			if (StringUtils.isNumeric(p)&&!p.trim().equals("")){
				codes.add(Integer.parseInt(p));
			}else {
				buffer.append(p);
				buffer.append(',');
			}
		});
		List<Integer> codesSort = codes.stream().sorted().collect(Collectors.toList());
		for (int i = 0; i < codesSort.size();i++) {
		    Integer min = codesSort.get(i);
		    Integer max = 0;
			for (int j=i+1;j<codesSort.size();j++){
			    boolean flag = checkNumCon(codesSort.get(i),codesSort.get(j));
			    if (flag){
			        max = codesSort.get(j);
					i=j;
                }else {
			        break;
                }
            }
			if (max>min){
			    buffer.append(min);
			    buffer.append('~');
			    buffer.append(max);
			    buffer.append(',');
            }else {
			    buffer.append(min);
			    if (i!=codesSort.size()-1)
			    	buffer.append(',');
            }
		}
		String s =  buffer.toString();
		return s;
	}

	//判断数字是否连续
	public boolean checkNumCon(Integer a,Integer b){
	    if (Math.abs(a-b)==1){
            return true;
        }else {
            return false;
        }
    }
	@Override
	public List<TdbYjMFlowTraintypeCode> selectFlowID(TdbYjMFlowTraintypeCode tdbYjMFlowTraintypeCode) {
		// TODO Auto-generated method stub
		List<TdbYjMFlowTraintypeCode> list = tdbYjMFlowTraintypeCodeMapper.selectFlowID(tdbYjMFlowTraintypeCode);
		return list;
	}
}
